Contentfulで投稿した画像をGatsbyで最適化して出力してみる
どうも、ベルリンオフィスの小西です。
現在、Gatsbyでの画像の取り扱いには Gatsby Image plugin( gatsby-plugin-image
) が便利です(旧公式プラグイン gatsby-image
はすでに非推奨)。
Gatsby Image plugin は画像のレスポンシブ最適化、スタイリング、読み込み方法の指定("eager" ∣ "lazy”)などが可能で、これ一つで静的・ダイナミックどちらの画像の出力にも対応できます。また gatsby-image
より画像の読み込み方法の簡素化、使い勝手の向上が図られています。
ヘッドレスCMSのContentfulから投稿された画像をGatsbyで取得&表示させる場合も、ただ <img>
で出力するのではなく、最適化して表示することが可能です。
今回はContentful側での投稿パターンに応じて画像を最適化する方法を紹介します。
前提
- Gatsby: Ver.4 以降
- Gatsbyプラグイン
gatsby-source-contentful
: Ver.7以降
1. コンテンツモデルが Media
として投稿された画像の場合
Contentful側
Contentfulのコンテンツモデル = Media
は、画像を含むメディアアセットの投稿に利用できます。
例えば記事のサムネイル、商品イメージなど、記事中の本文とは独立したメディアの登録に最適です。
Contentfulダッシュボードでいうと下記が該当します。
Gatsby側コード
<GatsbyImage>
コンポーネントを使います。
Gatsbyプラグイン gatsby-source-contentful
のGatsby Ver4に互換性のあるバージョンでは、Contentfulから取得した画像は gatsbyImageData
オブジェクトを持つため、それをコンポーネントの必須image属性として渡します。
実際のページにサムネイルを表示するコードは下記のようになります。
import React from "react"; import { graphql } from "gatsby"; import { GatsbyImage } from "gatsby-plugin-image" const SamplePage = ({ data }) => { const post = data.contentfulSamplePost; return ( <> <h1>{post.title}</h1> <GatsbyImage image={post.thumbnail.gatsbyImageData} alt={post.thumbnail.title} /> </> ) } export default SamplePage export const pageQuery = graphql` query { contentfulSamplePost( slug: {eq: "sample"} ) { title thumbnail { title gatsbyImageData } } } `;
<GatsbyImage>
で利用できるオプション
gatsbyImageData
オブジェクトはGatsby Image pluginの仕様に沿うため、さまざまなオプションが利用可能です。
指定方法はGraphQL リゾルバにオプションを投げるだけです。
例
export const pageQuery = graphql` query { contentfulSamplePost( slug: {eq: "sample"} ) { thumbnail { gatsbyImageData( width: 600 placeholder: BLURRED formats: [AUTO, WEBP, AVIF] quality: 10 ) } } } `;
その他のオプションを詳しく知りたい方は → https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/#gatsbyimage
ただし、上記は便利ですが、記事の文中などに差し込まれる画像には適用されません。
記事中に埋め込まれた画像の最適化については次に説明します。
2. マークダウン記事中の画像の場合
Contentfulで長文を投稿する場合マークダウン形式が最も一般的です。記事中にメディアを埋め込むこともでき、それらは 通常の <img> タグとしてGatsbyに渡ってくるため、そのまま出力すると上で紹介したGatsbyImage
のような最適化ができません。
そのため、例えばContentfulで非常に大きなサイズの画像が投稿されていた場合、Gatsbyアプリ側のwidthを超えて不要なサイズの画像が読み込まれてしまい、ユーザーフレンドリーではありません。
この問題を、公式プラグイン gatsby-remark-images-contentful
を使って解決します。
Contentful側
今回利用するプラグインはMarkdown式の本文で動くため、Contentful側では [Long text] 形式の長文入力フィールドを使います。
↓
Gatsby側設定&コード
必要なパッケージのインストール
npm install gatsby-remark-images-contentful
module.exports = { ...(略) plugins: [ `gatsby-plugin-image`, { resolve: `gatsby-transformer-remark`, options: { plugins: [ { resolve: `gatsby-remark-images-contentful`, options: { maxWidth: 600, showCaptions: true, }, }, ], }, }, ...(略) ], }
設定は以上です。
これだけでContentfulマークダウン内の画像に対して、遅延読み込みなどの最適化が実施されます。
オプションはフロントのテンプレート側ではなく、 gatsby-config.js
で指定します。
gatsby-remark-images-contentful
で利用できるオプション
- maxWidth … 画像の最大横幅を指定します(デフォルト:
650
) - linkImagesToOriginal … リサイズや最適化がされていないオリジナル画像へのリンクを自動で貼ります(デフォルト:
true
) - showCaptions … 画像のタイトルを各画像のキャプションとして表示します(デフォルト:
false
) - wrapperStyle … 画像をdivでラップするスタイリングを指定します(例: margin-bottom:10px; background: red;)
- backgroundColor … イメージ背景色の指定(デフォルト:
white
) - withWebp … WebPを追加で生成し
srcset
に追加します(デフォルト:false
) - loading lazy … 画像の読み込み方法(
lazy
,eager
,auto
)を指定します(デフォルト:lazy
)
gatsby-remark-images-contentful
のインストールに問題が起こったら
gatsby-remark-images-contentful
のインストール中でエラーが発生することがあります。
必須プラグインがない場合
There was a problem loading plugin "gatsby-transformer-remark". Perhaps you need to install its package?
Use --verbose to see actual error.
素直に親プラグインをインストールします。
npm install gatsby-transformer-remark
プラグインの互換性で怒られる場合
Something went wrong installing the "sharp" module
dlopen(/Users/misiek/dev/gatsby-starter-blog/node_modules/sharp/build/Release/sharp.node, 1): Library not loaded: @rpath/libglib-2.0.dylib
Referenced from: /Users/misiek/dev/gatsby-starter-blog/node_modules/sharp/build/Release/sharp.node
Reason: Incompatible library version: sharp.node requires version 6001.0.0 or later, but libglib-2.0.dylib provides version 5801.0.0
関連プラグインをアップデートしましょう。
npm install gatsby-plugin-sharp gatsby-plugin-manifest gatsby-remark-images-contentful gatsby-source-contentful gatsby-transformer-sharp gatsby-transformer-sqip
以上、Contentfulの画像をGatsbyで最適化する2パターンを紹介してみました。
クラスメソッドはContentfulのパートナーとして導入のお手伝いをさせていただいています。